module chess {
	export class BoardUtils {
		public constructor() {
		}

		public static fixScore = function (type) {
			if (type < chess.ChessConst.score.FOUR && type >= chess.ChessConst.score.BLOCKED_FOUR) {

				if (type >= chess.ChessConst.score.BLOCKED_FOUR && type < (chess.ChessConst.score.BLOCKED_FOUR + chess.ChessConst.score.THREE)) {
					//单独冲四，意义不大
					return chess.ChessConst.score.THREE
				} else if (type >= chess.ChessConst.score.BLOCKED_FOUR + chess.ChessConst.score.THREE && type < chess.ChessConst.score.BLOCKED_FOUR * 2) {
					return chess.ChessConst.score.FOUR  //冲四活三，比双三分高，相当于自己形成活四
				} else {
					//双冲四 比活四分数也高
					return chess.ChessConst.score.FOUR * 2
				}
			}
			return type
		}

		public static starTo(point, points?) {
			if (!points || !points.length) return false
			const a = point
			for (let i = 0; i < points.length; i++) {
				// 距离必须在5步以内
				const b = points[i]
				if ((Math.abs(a[0] - b[0]) > 4 || Math.abs(a[1] - b[1]) > 4)) return false
				// 必须在米子方向上
				if (!(a[0] === b[0] || a[1] === b[1] || (Math.abs(a[0] - b[0]) === Math.abs(a[1] - b[1])))) return false
			}
			return true
		}

		public static scorePoint(b, px, py, role, dir?) {
			let board = b.board
			let result = 0,
				radius = 8,
				empty = 0
			let count = 0, block = 0, secondCount = 0  //另一个方向的count

			let len = board.length

			function reset() {
				count = 1
				block = 0
				empty = -1
				secondCount = 0  //另一个方向的count
			}


			if (dir === undefined || dir === 0) {
				reset()

				// -

				for (let i = py + 1; true; i++) {
					if (i >= len) {
						block++
						break
					}
					let t = board[px][i]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && i < len - 1 && board[px][i + 1] == role) {
							empty = count
							continue
						} else {
							break
						}
					}
					if (t === role) {
						count++
						continue
					} else {
						block++
						break
					}
				}


				for (let i = py - 1; true; i--) {
					if (i < 0) {
						block++
						break
					}
					let t = board[px][i]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && i > 0 && board[px][i - 1] == role) {
							empty = 0  //注意这里是0，因为是从右往左走的
							continue
						} else {
							break
						}
					}
					if (t === role) {
						secondCount++
						empty !== -1 && empty++  //注意这里，如果左边又多了己方棋子，那么empty的位置就变大了
						continue
					} else {
						block++
						break
					}
				}

				count += secondCount

				b.scoreCache[role][0][px][py] = chess.BoardUtils.countToScore(count, block, empty)
			}
			result += b.scoreCache[role][0][px][py]

			if (dir === undefined || dir === 1) {

				// |
				reset()

				for (let i = px + 1; true; i++) {
					if (i >= len) {
						block++
						break
					}
					let t = board[i][py]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && i < len - 1 && board[i + 1][py] == role) {
							empty = count
							continue
						} else {
							break
						}
					}
					if (t === role) {
						count++
						continue
					} else {
						block++
						break
					}
				}

				for (let i = px - 1; true; i--) {
					if (i < 0) {
						block++
						break
					}
					let t = board[i][py]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && i > 0 && board[i - 1][py] == role) {
							empty = 0
							continue
						} else {
							break
						}
					}
					if (t === role) {
						secondCount++
						empty !== -1 && empty++  //注意这里，如果左边又多了己方棋子，那么empty的位置就变大了
						continue
					} else {
						block++
						break
					}
				}

				count += secondCount

				b.scoreCache[role][1][px][py] = chess.BoardUtils.countToScore(count, block, empty)
			}
			result += b.scoreCache[role][1][px][py]


			// \
			if (dir === undefined || dir === 2) {
				reset()

				for (let i = 1; true; i++) {
					let x = px + i, y = py + i
					if (x >= len || y >= len) {
						block++
						break
					}
					let t = board[x][y]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && (x < len - 1 && y < len - 1) && board[x + 1][y + 1] == role) {
							empty = count
							continue
						} else {
							break
						}
					}
					if (t === role) {
						count++
						continue
					} else {
						block++
						break
					}
				}

				for (let i = 1; true; i++) {
					let x = px - i, y = py - i
					if (x < 0 || y < 0) {
						block++
						break
					}
					let t = board[x][y]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && (x > 0 && y > 0) && board[x - 1][y - 1] == role) {
							empty = 0
							continue
						} else {
							break
						}
					}
					if (t === role) {
						secondCount++
						empty !== -1 && empty++  //注意这里，如果左边又多了己方棋子，那么empty的位置就变大了
						continue
					} else {
						block++
						break
					}
				}

				count += secondCount

				b.scoreCache[role][2][px][py] = chess.BoardUtils.countToScore(count, block, empty)
			}
			result += b.scoreCache[role][2][px][py]


			// /
			if (dir === undefined || dir === 3) {
				reset()

				for (let i = 1; true; i++) {
					let x = px + i, y = py - i
					if (x < 0 || y < 0 || x >= len || y >= len) {
						block++
						break
					}
					let t = board[x][y]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && (x < len - 1 && y < len - 1) && board[x + 1][y - 1] == role) {
							empty = count
							continue
						} else {
							break
						}
					}
					if (t === role) {
						count++
						continue
					} else {
						block++
						break
					}
				}

				for (let i = 1; true; i++) {
					let x = px - i, y = py + i
					if (x < 0 || y < 0 || x >= len || y >= len) {
						block++
						break
					}
					let t = board[x][y]
					if (t === chess.ChessConst.role.empty) {
						if (empty == -1 && (x > 0 && y > 0) && board[x - 1][y + 1] == role) {
							empty = 0
							continue
						} else {
							break
						}
					}
					if (t === role) {
						secondCount++
						empty !== -1 && empty++  //注意这里，如果左边又多了己方棋子，那么empty的位置就变大了
						continue
					} else {
						block++
						break
					}
				}

				count += secondCount

				b.scoreCache[role][3][px][py] = chess.BoardUtils.countToScore(count, block, empty)
			}
			result += b.scoreCache[role][3][px][py]

			return result
		}

		public static countToScore(count, block, empty) {
			let score = chess.ChessConst.score;
			if (empty === undefined) empty = 0

			//没有空位
			if (empty <= 0) {
				if (count >= 5) return score.FIVE
				if (block === 0) {
					switch (count) {
						case 1: return score.ONE
						case 2: return score.TWO
						case 3: return score.THREE
						case 4: return score.FOUR
					}
				}

				if (block === 1) {
					switch (count) {
						case 1: return score.BLOCKED_ONE
						case 2: return score.BLOCKED_TWO
						case 3: return score.BLOCKED_THREE
						case 4: return score.BLOCKED_FOUR
					}
				}

			} else if (empty === 1 || empty == count - 1) {
				//第1个是空位
				if (count >= 6) {
					return score.FIVE
				}
				if (block === 0) {
					switch (count) {
						case 2: return score.TWO / 2
						case 3: return score.THREE
						case 4: return score.BLOCKED_FOUR
						case 5: return score.FOUR
					}
				}

				if (block === 1) {
					switch (count) {
						case 2: return score.BLOCKED_TWO
						case 3: return score.BLOCKED_THREE
						case 4: return score.BLOCKED_FOUR
						case 5: return score.BLOCKED_FOUR
					}
				}
			} else if (empty === 2 || empty == count - 2) {
				//第二个是空位
				if (count >= 7) {
					return score.FIVE
				}
				if (block === 0) {
					switch (count) {
						case 3: return score.THREE
						case 4:
						case 5: return score.BLOCKED_FOUR
						case 6: return score.FOUR
					}
				}

				if (block === 1) {
					switch (count) {
						case 3: return score.BLOCKED_THREE
						case 4: return score.BLOCKED_FOUR
						case 5: return score.BLOCKED_FOUR
						case 6: return score.FOUR
					}
				}

				if (block === 2) {
					switch (count) {
						case 4:
						case 5:
						case 6: return score.BLOCKED_FOUR
					}
				}
			} else if (empty === 3 || empty == count - 3) {
				if (count >= 8) {
					return score.FIVE
				}
				if (block === 0) {
					switch (count) {
						case 4:
						case 5: return score.THREE
						case 6: return score.BLOCKED_FOUR
						case 7: return score.FOUR
					}
				}

				if (block === 1) {
					switch (count) {
						case 4:
						case 5:
						case 6: return score.BLOCKED_FOUR
						case 7: return score.FOUR
					}
				}

				if (block === 2) {
					switch (count) {
						case 4:
						case 5:
						case 6:
						case 7: return score.BLOCKED_FOUR
					}
				}
			} else if (empty === 4 || empty == count - 4) {
				if (count >= 9) {
					return score.FIVE
				}
				if (block === 0) {
					switch (count) {
						case 5:
						case 6:
						case 7:
						case 8: return score.FOUR
					}
				}

				if (block === 1) {
					switch (count) {
						case 4:
						case 5:
						case 6:
						case 7: return score.BLOCKED_FOUR
						case 8: return score.FOUR
					}
				}

				if (block === 2) {
					switch (count) {
						case 5:
						case 6:
						case 7:
						case 8: return score.BLOCKED_FOUR
					}
				}
			} else if (empty === 5 || empty == count - 5) {
				return score.FIVE
			}

			return 0
		}

		public static getOpen26() {
			let getBoard = function () {
				return [
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
				]
			}

			const open26 = {}

			// 疏
			open26["shuyue"] = getBoard()
			open26["shuyue"][5][5] = 1
			open26["shuyue"]["name"] = '疏月'

			// 溪
			open26["xiyue"] = getBoard()
			open26["xiyue"][5][6] = 1
			open26["xiyue"]["name"] = '溪月'

			// 寒
			open26["hanyue"] = getBoard()
			open26["hanyue"][5][7] = 1
			open26["hanyue"]["name"] = '寒月'

			// 残
			open26["canyue"] = getBoard()
			open26["canyue"][6][5] = 1
			open26["canyue"]["name"] = '残月'

			// 花
			open26["huayue"] = getBoard()
			open26["huayue"][6][6] = 1
			open26["huayue"]["name"] = '花月'

			// 金
			open26["jinyue"] = getBoard()
			open26["jinyue"][7][5] = 1
			open26["jinyue"]["name"] = '金月'

			// 雨
			open26["yuyue"] = getBoard()
			open26["yuyue"][7][6] = 1
			open26["yuyue"]["name"] = '雨月'

			// 新
			open26["xinyue"] = getBoard()
			open26["xinyue"][8][5] = 1
			open26["xinyue"]["name"] = '新月'

			// 丘
			open26["qiuyue"] = getBoard()
			open26["qiuyue"][8][6] = 1
			open26["qiuyue"]["name"] = '丘月'

			// 松
			open26["songyue"] = getBoard()
			open26["songyue"][8][7] = 1
			open26["songyue"]["name"] = '松月'

			// 游
			open26["youyue"] = getBoard()
			open26["youyue"][9][5] = 1
			open26["youyue"]["name"] = '游月'

			// 山
			open26["shanyue"] = getBoard()
			open26["shanyue"][9][6] = 1
			open26["shanyue"]["name"] = '山月'

			// 瑞
			open26["ruiyue"] = getBoard()
			open26["ruiyue"][9][7] = 1
			open26["ruiyue"]["name"] = '瑞月'

			getBoard = function () {
				return [
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
					[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
				]
			}

			// 流
			open26["liuyue"] = getBoard()
			open26["liuyue"][5][5] = 1
			open26["liuyue"]["name"] = '流月'

			// 水
			open26["shuiyue"] = getBoard()
			open26["shuiyue"][5][6] = 1
			open26["shuiyue"]["name"] = '水月'

			// 恒
			open26["hengyue"] = getBoard()
			open26["hengyue"][5][7] = 1
			open26["hengyue"]["name"] = '恒月'

			// 峡
			open26["xiayue"] = getBoard()
			open26["xiayue"][5][8] = 1
			open26["xiayue"]["name"] = '峡月'

			// 长
			open26["changyue"] = getBoard()
			open26["changyue"][5][9] = 1
			open26["changyue"]["name"] = '长月'

			// 岚
			open26["lanyue"] = getBoard()
			open26["lanyue"][6][5] = 1
			open26["lanyue"]["name"] = '岚月'

			// 浦
			open26["puyue"] = getBoard()
			open26["puyue"][6][6] = 1
			open26["puyue"]["name"] = '浦月'

			// 云
			open26["yunyue"] = getBoard()
			open26["yunyue"][6][7] = 1
			open26["yunyue"]["name"] = '云月'

			// 明
			open26["mingyue"] = getBoard()
			open26["mingyue"][7][5] = 1
			open26["mingyue"]["name"] = '明月'

			// 银
			open26["yinyue"] = getBoard()
			open26["yinyue"][7][6] = 1
			open26["yinyue"]["name"] = '银月'

			// 名
			open26["ming2yue"] = getBoard()
			open26["ming2yue"][8][5] = 1
			open26["ming2yue"]["name"] = '名月'

			// 斜
			open26["xieyue"] = getBoard()
			open26["xieyue"][8][6] = 1
			open26["xieyue"]["name"] = '斜月'

			// 慧
			open26["huiyue"] = getBoard()
			open26["huiyue"][9][5] = 1
			open26["huiyue"]["name"] = '慧月'

			return open26;
		}

	}
}